package huanzhao.erp.controller;

import huanzhao.erp.domain.annotation.AvoidClear;
import huanzhao.erp.domain.annotation.CheckAssignable;
import huanzhao.erp.domain.annotation.CheckPosition;
import huanzhao.erp.domain.annotation.CheckTask;
import huanzhao.erp.domain.po.Result;
import huanzhao.erp.domain.types.DeptPositionType;
import huanzhao.erp.domain.types.StaffType;
import huanzhao.erp.domain.types.TaskType;
import huanzhao.erp.service.PhoneService;
import huanzhao.erp.service.TaskService;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.Range;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.util.List;


/**
 * @author April
 * 2024/6/17 下午8:50
 * @version 1.0
 */
@RestController
@Slf4j
@Validated
@RequestMapping("/api/process")
public class MainProcessController {

    private final TaskService taskService;
    private final PhoneService phoneService;

    public MainProcessController(TaskService taskService, PhoneService phoneService) {
        this.taskService = taskService;
        this.phoneService = phoneService;
    }

    /**
     * 接收任务
     *
     * @param take 是否接收该任务
     * @return Result<?>
     * 2024/10/7 16:59:18
     */
    @PostMapping("take")
    @AvoidClear
    public Result<?> takeTask(@RequestParam @CheckTask(completable = false) long taskId,
                              @RequestParam boolean take,
                              @RequestParam(required = false) String comment) {
        return taskService.takeTask(taskId, take, comment);
    }

    /**
     * 库房签收手机
     *
     * @return Result<?>
     * 2024/6/17 下午9:00:49
     */
    @PostMapping("/sign")
    @AvoidClear
    @CheckPosition(DeptPositionType.WAREHOUSER)
    public Result<?> signPhone(@RequestParam @NotBlank String imei, @RequestParam(required = false) String comment) {
        return phoneService.signPhone(imei, comment);
    }

    /**
     * 库房分货
     *
     * @param phoneIds    手机id数组
     * @param purchaserId 采购人id
     * @return Result<?>
     * 2024/10/7 17:39:21
     */
    @PostMapping("distribute")
    @AvoidClear
    @CheckPosition(DeptPositionType.WAREHOUSER)
    public Result<List<Long>> distributePhones(@RequestParam @NotNull @Size(min = 1) List<Long> phoneIds,
                                               @RequestParam @CheckAssignable(StaffType.PURCHASER) long purchaserId,
                                               @RequestParam(required = false) String comment) {
        return phoneService.distributePhones(phoneIds, purchaserId, comment);
    }

    /**
     * 采购员对手机初检
     *
     * @param qc      是否质检
     * @param teamId  渠道id，质检时需要指定
     * @param staffId 员工id：操作为质检时质检员id（根据渠道确定），退货时为库管id（为toC渠道时不指定）
     * @return Result<?>
     * 2024/10/7 17:39:51
     */
    @PostMapping("/precheck")
    public Result<?> precheckPhone(@RequestParam boolean qc,
                                   @RequestParam @CheckTask(TaskType.FIRST_CHECK) long taskId,
                                   @RequestParam(required = false) Long teamId,
                                   @RequestParam(required = false) @CheckAssignable Long staffId,
                                   @RequestParam(required = false) String comment) {

        return phoneService.precheckPhone(qc, taskId, teamId, staffId, comment);
    }

    /**
     * 采购员对手机二次检查
     * 二次检查，不能退货，只能送质检。包含流程图中的维修后初检、转库初检、退货后初检几种任务类型。
     *
     * @param staffId 可选，若手机为toC渠道则不填，否则填质检员id
     * @param teamId  若要更换渠道，则填写该字段
     * @return Result<?>
     * 2024/10/7 17:41:27
     */
    @PostMapping("recheck")
    public Result<?> recheckPhone(@RequestParam @CheckTask({TaskType.RECHECK, TaskType.CHECK_AFTER_RETURN, TaskType.CHECK_WHEN_TRANSFER}) long taskId,
                                  @RequestParam(required = false) @CheckAssignable Long staffId,
                                  @RequestParam(required = false) Long teamId,
                                  @RequestParam(required = false) String comment) {
        return phoneService.recheckPhone(taskId, staffId, teamId, comment);
    }

    /**
     * 库房进行采购退货
     *
     * @param taskId    任务id
     * @param waybillNo 运单号
     * @return Result<?>
     * 2024/6/17 下午9:03:52
     */
    @DeleteMapping("/return")
    public Result<?> returnPhone(@RequestParam @CheckTask(TaskType.PURCHASE_RETURN) long taskId,
                                 @RequestParam @NotBlank String waybillNo,
                                 @RequestParam(required = false) String comment) {

        return phoneService.returnPhone(taskId, waybillNo, comment);
    }

    /**
     * C端销售渠道组长指定质检员
     *
     * @param taskId  任务id
     * @param staffId 员工id
     * @return Result<?>
     * 2024/6/17 下午9:05:58
     */
    @PostMapping("/designate")
    public Result<?> designateQCStaff(@RequestParam @CheckTask(TaskType.DESIGNATE_QC) long taskId,
                                      @RequestParam @CheckAssignable long staffId,
                                      @RequestParam(required = false) String comment) {
        return taskService.designateQCStaff(taskId, staffId, comment);
    }

    /**
     * 质检员对手机进行质检
     *
     * @param taskId    任务id
     * @param qualified 质检是否合格
     * @param staffId   质检合格为录入id，不合格为采购员id
     * @return Result<?>
     * 2024/6/17 下午9:07:33
     */
    @PostMapping("/qc")
    public Result<?> checkPhone(@RequestParam @CheckTask(TaskType.QC) long taskId,
                                @RequestParam @CheckAssignable long staffId,
                                @RequestParam boolean qualified,
                                @RequestParam(required = false) String comment) {
        return taskService.checkPhone(taskId, staffId, qualified, comment);
    }

    /**
     * 录入小组进行手机录入
     *
     * @param taskId  任务id
     * @param staffId 上架员id
     * @return Result<?>
     * 2024/6/17 下午9:06:45
     */
    @PostMapping("/input")
    public Result<?> enterPhone(@RequestParam @CheckTask(TaskType.ENTER) long taskId,
                                @RequestParam @CheckAssignable long staffId,
                                @RequestParam(required = false) String comment) {
        return taskService.enterPhone(taskId, staffId, comment);
    }


    /**
     * 上架小组将手机上架
     *
     * @param purchaserId 员工id：到哪个采购员
     * @param soldPrice   上架销售金额,，使用字符串表示
     * @param degree      上架成色
     * @return Result<?>
     * 2024/10/7 17:47:30
     */
    @PostMapping("/publish")
    public Result<?> publish(@RequestParam @CheckTask(TaskType.PUBLISH) long taskId,
                             @RequestParam @CheckAssignable(StaffType.PURCHASER) long purchaserId,
                             @RequestParam BigDecimal soldPrice,
                             @RequestParam @Range(max = 100) int degree,
                             @RequestParam(required = false) String comment) {
        return taskService.publish(taskId, purchaserId, soldPrice, degree, comment);
    }

    /**
     * 采购接收上架
     *
     * @param warehouserId 员工id：到哪个库管员
     * @return Result<?>
     * 2024/10/7 17:49:07
     */
    @PostMapping("receive/publish")
    public Result<?> receivePublish(@RequestParam @CheckTask(TaskType.RECEIVE_PUBLISH) long taskId,
                                    @RequestParam @CheckAssignable(StaffType.WAREHOUSER) long warehouserId,
                                    @RequestParam(required = false) String comment) {
        return taskService.receivePublish(taskId, warehouserId, comment);
    }

    /**
     * 库管将手机入库
     *
     * @param taskId      任务id
     * @param storageArea 存放区域
     * @param number      库位号
     * @return Result<?>
     * 2024/6/17 下午9:09:49
     */
    @PostMapping("/stock")
    public Result<?> stockPhone(@RequestParam @CheckTask(TaskType.STOCK) long taskId,
                                @RequestParam @NotBlank String storageArea,
                                @RequestParam(required = false) String number,
                                @RequestParam(required = false) String comment) {
        return taskService.stockPhone(taskId, storageArea, number, comment);
    }

    /**
     * 采购员将手机发给维修部门
     *
     * @param recheck 是否进行二次检查（用于重新分渠道）
     * @return Result<?>
     * 2024/10/7 17:49:49
     */
    @PostMapping("/send/repair")
    public Result<?> sendToRepair(@RequestParam @CheckTask(TaskType.PURCHASER_SEND_REPAIR) long taskId,
                                  @RequestParam boolean recheck,
                                  @RequestParam(required = false) String comment) {
        return taskService.sendToRepair(taskId, recheck, comment);
    }

    /**
     * 维修主管对手机进行维修评估
     *
     * @param option  操作：0->维修，1->入库，2->报损
     * @param staffId 送回仓库时填写库管id，报损则不填
     * @return Result<?>
     * 2024/6/17 下午9:47:11
     */
    @PostMapping("/repair/evaluate")
    public Result<?> evaluateRepair(@RequestParam @CheckTask(TaskType.REPAIR_EVALUATE) long taskId,
                                    @RequestParam @Range(max = 2) int option,
                                    @RequestParam(required = false) @CheckAssignable Long staffId,
                                    @RequestParam(required = false) String comment) {
        return taskService.evaluateRepair(taskId, option, staffId, comment);
    }

    /**
     * 维修组长分派维修
     *
     * @param outsource 是否为送修
     * @param staffId   内部维修时为维修员id，送修时为库管id
     * @return Result<?>
     * 2024/10/7 18:06:09
     */
    @PostMapping("/repair/dispatch")
    public Result<?> dispatchRepair(@RequestParam @CheckTask(TaskType.DESIGNATE_REPAIR) long taskId,
                                    @RequestParam boolean outsource,
                                    @RequestParam @CheckAssignable long staffId,
                                    @RequestParam(required = false) String comment) {
        return taskService.dispatchRepair(taskId, outsource, staffId, comment);
    }

    /**
     * 完成手机维修
     * 对于普通的维修任务和外送维修回来的时候的维修完成填报任务均适用
     *
     * @param hasCost    是否增加维修成本
     * @param cost       增加的维修成本，用字符串表示
     * @param repaired   手机是否修好
     * @param costReason 维修成本说明
     * @return Result<?>
     * 2024/10/7 18:08:41
     */
    @PostMapping("/repair/finish")
    public Result<?> finishRepair(@RequestParam @CheckTask({TaskType.REPAIR, TaskType.FILL_OUTSOURCE_REPAIR_RESULT}) long taskId,
                                  @RequestParam boolean hasCost,
                                  @RequestParam(required = false) BigDecimal cost,
                                  @RequestParam boolean repaired,
                                  @RequestParam(required = false) String costReason,
                                  @RequestParam(required = false) String comment) {
        return taskService.finishRepair(taskId, hasCost, cost, repaired, costReason, comment);
    }

    /**
     * 库管员发货送修的手机
     *
     * @param needExpress 是否需要发快递
     * @param waybill     运单号，需要发快递时填写
     * @return Result<?>
     * 2024/10/7 18:10:19
     */
    @PostMapping("repair/out/ship")
    public Result<?> outRepairShip(@RequestParam @CheckTask(TaskType.OUTSOURCE_REPAIR_SHIP) long taskId,
                                   @RequestParam boolean needExpress,
                                   @RequestParam(required = false) String waybill,
                                   @RequestParam(required = false) String comment) {
        return taskService.outRepairShip(taskId, needExpress, waybill, comment);
    }

    /**
     * 库管员签收送修的手机
     *
     * @return Result<?>
     * 2024/10/7 18:11:33
     */
    @PostMapping("repair/out/sign")
    public Result<?> outRepairSign(@RequestParam @CheckTask(TaskType.OUTSOURCE_REPAIR_SIGN) long taskId,
                                   @RequestParam(required = false) String comment) {
        return taskService.outRepairSign(taskId, comment);
    }

    /**
     * 库管员接收维修完成的手机
     *
     * @param staffId 员工id：任务为售后单时，为库管员id（通常为自己），否则为采购id
     * @return Result<?>
     * 2024/10/7 18:11:51
     */
    @PostMapping("/repair/warehouse/receive")
    public Result<?> receiveRepairedPhone(@RequestParam @CheckTask(TaskType.RECEIVE_REPAIR) long taskId,
                                          @RequestParam @CheckAssignable long staffId,
                                          @RequestParam(required = false) String comment) {
        return taskService.receiveRepairedPhone(taskId, staffId, comment);
    }

    /**
     * 库房进行转库
     *
     * @param purchaserId 员工id：指定的采购员id
     * @param teamId      新的渠道id
     * @return Result<?>
     * 2024/10/7 18:13:02
     */
    @PostMapping("transfer")
    @AvoidClear
    @CheckPosition(DeptPositionType.WAREHOUSER)
    public Result<?> transferPhone(@RequestParam @NotBlank String imei,
                                   @RequestParam @CheckAssignable(StaffType.PURCHASER) long purchaserId,
                                   @RequestParam long teamId,
                                   @RequestParam(required = false) String comment) {
        return phoneService.transferPhone(imei, purchaserId, teamId, comment);
    }
}
